﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraEditors;
using ProgNetDxComponents.ExtenderProviders;
using System.ComponentModel.Design;
using DevExpress.XtraEditors.Registrator;
using System.Reflection;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;

namespace ProgNetDxComponents.Design.Creators
{
    public partial class CreateEditorsForm : XtraForm
    {
        public DataSet DataSet
        {
            get;
            set;
        }
        public ModeProvider ModeProvider
        {
            get;
            set;
        }
        public LanguageProvider LanguageProvider
        {
            get;
            set;
        }
        public IDesignerHost Designer
        {
            get;
            set;
        }
        private Point LabelLocation = new Point(40, 40);
        private Point EditLocation = new Point(200, 40);
        private Size LabelSize = new Size(150, 20);
        private Size EditSize = new Size(120, 20);
        public Control ParentContainer
        {
            get;
            set;
        }
        public OptionProvider OptionProvider
        {
            get;
            set;
        }
        public bool Options
        {
            get { return OptionProvider != null; }
        }
        public CreateEditorsForm()
        {
            InitializeComponent();

            foreach (EditorClassInfo info in EditorRegistrationInfo.Default.Editors)
            {
                repItemEditor.Items.Add(info.Name);
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (ParentContainer == null)
                Close();

            if (Options)
            {
                splitContainerControl1.PanelVisibility = SplitPanelVisibility.Panel1;

                colTable.Visible = false;
                colColumn.Caption = "Option";

                Type t = (ProgNetComponents.Constants.ProgNetConstNamespace + ".OptionNames").GetAssemblyType();
                if (t != null)
                {
                    PropertyInfo _Property = null;
                    FieldInfo _Field = null;
                    MethodInfo _Refresh = null;
                    Dictionary<string, object> list = null;

                    if (t != null)
                    {
                        _Refresh = t.GetMethod("Refresh", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                        if (_Refresh != null)
                        {
                            _Refresh.Invoke(null, null);
                        }
                        _Property = t.GetSingleProperty("StaticCollection", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
                        if (_Property == null)
                            _Field = t.GetSingleField("StaticCollection", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);

                        if (_Property != null)
                        {
                            list = _Property.GetValue(null) as Dictionary<string, object>;
                        }
                        else if (_Field != null)
                        {
                            list = _Field.GetValue(null) as Dictionary<string, object>;
                        }
                        
                    }
                    foreach (object s in list.Values)
                    {
                        createEditorsDataSet1.AllColumns.Rows.Add(" ", s.AsString(), DBNull.Value, false);
                    }
                }
            }
            else
                if (DataSet != null)
                {
                    foreach (DataTable dt in DataSet.Tables)
                    {
                        createEditorsDataSet1.AllTables.Rows.Add(dt.TableName, false, false);
                        foreach (DataColumn col in dt.Columns)
                        {
                            createEditorsDataSet1.AllColumns.Rows.Add(dt.TableName, col.ColumnName, DBNull.Value, false);
                            createEditorsDataSet1.TablesColumns.Rows.Add(dt.TableName, col.ColumnName, true);
                        }
                    }
                }

        }

        private void btnCreateEditors_Click(object sender, EventArgs e)
        {
            if (Designer != null)
            {
                DataRow[] rows = createEditorsDataSet1.AllColumns.Select("Editor is not null");
                foreach (DataRow r in rows)
                {
                    CreateEditor(r);
                }
                rows = createEditorsDataSet1.AllTables.Select("Create = 1");
                foreach (DataRow r in rows)
                {
                    CreateGrid(r);
                }
            }
        }

        private void AddControl(Control c)
        {
            if (ParentContainer != null)
            {
                if (c is LabelControl)
                {
                    c.Location = GetLabelPosition();
                    c.Size = LabelSize;
                }
                else if (c is BaseEdit)
                {
                    c.Location = GetEditPosition();
                    if (c is CheckEdit)
                    {
                        c.Width = EditSize.Width;
                        if (c.Text.Mesure(c.Font).Width > c.Width - 10)
                            c.Width = c.Text.Mesure(c.Font).Width + 10;
                    }
                    else
                        c.Width = EditSize.Width;
                }
                else
                {
                    c.Location = GetLabelPosition();
                    c.Size = new Size(450, 250);
                }

                ParentContainer.Controls.Add(c);
            }
        }

        private bool RootHasChildInRegion(Point p, Size s)
        {
            return ParentContainer.HasChildInRegion(p, s);
        }

        private Point GetLabelPosition()
        {
            Size s = new Size(LabelSize.Width + EditSize.Width + 3, LabelSize.Height);
            while (RootHasChildInRegion(LabelLocation, s))
            {
                LabelLocation.Y += LabelSize.Height + 5;
                if (LabelLocation.Y > ParentContainer.Height)
                {
                    LabelLocation.Y = 40;
                    LabelLocation.X += LabelSize.Width + 3 + EditSize.Width + 20;
                    if (LabelLocation.X > ParentContainer.Width)
                        break;
                }

            }
            return LabelLocation;
        }

        private Point GetEditPosition()
        {
            while (RootHasChildInRegion(EditLocation, EditSize))
            {
                EditLocation.Y += EditSize.Height + 5;
                if (EditLocation.Y > ParentContainer.Height)
                {
                    EditLocation.Y = 40;
                    EditLocation.X += EditSize.Width + 3 + LabelSize.Width + 20;
                }
            }
            return EditLocation;
        }
        private void CreateEditor(DataRow row)
        {
            DesignerTransaction trans = null;
            try
            {
                trans = Designer.CreateTransaction();
                string name = row["Column"].AsString().ToUpper();

                if (row["Label"].AsBool())
                {
                    LabelControl label = Designer.CreateComponent(typeof(LabelControl), "lbl" + name) as LabelControl;
                    label.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Far;
                    label.AutoSizeMode = LabelAutoSizeMode.None;
                    if (LanguageProvider != null)
                    {
                        LanguageProvider.GetSettings(label).Surfix = ":";
                        LanguageProvider.GetSettings(label).LngString = row["Column"].AsString();
                    }
                    AddControl(label);
                }

                BaseEdit edit = Designer.CreateComponent(EditorRegistrationInfo.Default.Editors[row["Editor"].AsString()].EditorType, "edit" + name) as BaseEdit;
                if (edit != null)
                {
                    if (edit is ButtonEdit)
                    {
                        (edit as ButtonEdit).Properties.Buttons.Clear();
                        (edit as ButtonEdit).Properties.CreateDefaultButton();
                    }
                    if (edit is TextEdit)
                    {
                        (edit as TextEdit).Properties.NullText = "";
                    }
                    if (!Options)
                    {
                        edit.Properties.Assign(EditorRegistrationInfo.Default.CreateRepositoryItem(row["Editor"].AsString()));
                        edit.DataBindings.Add(new Binding("EditValue", DataSet, row["Table"].AsString() + "." + row["Column"].AsString()));
                    }
                    else
                    {
                        OptionProvider.GetSettings(edit).OptionName = row["Column"].AsString();
                    }
                    if (edit is CheckEdit)
                    {
                        if (row["Label"].AsBool())
                            (edit as CheckEdit).Text = "";
                        else
                        {
                            if (LanguageProvider != null)
                            {
                                LanguageProvider.GetSettings(edit).LngString = row["Column"].AsString();
                            }
                            else
                                edit.Text = row["Column"].AsString();
                        }
                    }
                    AddControl(edit);
                }
                trans.Commit();
            }
            catch (Exception ex)
            {
                ex.Log();
                ex.InnerException.Log("Inner: ");
            }
        }

        private void CreateGrid(DataRow row)
        {

            string name = row["Table"].AsString().ToUpper();
            if (row["Label"].AsBool())
            {
                LabelControl label = Designer.CreateComponent(typeof(LabelControl), "lbl" + name) as LabelControl;
                label.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near;
                label.AutoSizeMode = LabelAutoSizeMode.None;
                if (LanguageProvider != null)
                {
                    LanguageProvider.GetSettings(label).Surfix = ":";
                    LanguageProvider.GetSettings(label).LngString = row["Table"].AsString();
                }
                AddControl(label);
            }

            GridControl gc = Designer.CreateComponent(typeof(GridControl), "gc" + name) as GridControl;
            gc.DataSource = DataSet;
            gc.DataMember = name;
            GridView gv = gc.MainView as GridView;
            if (gv == null)
            {
                try
                {
                    gv = Designer.CreateComponent(typeof(GridView), "gv" + name) as GridView;
                    gc.MainView = gv;
                    if (gc.ViewCollection.Count == 0)
                        gc.ViewCollection.Add(gv);
                }
                catch { }
            }
            if (gv != null)
            {
                DataRow[] cols = createEditorsDataSet1.TablesColumns.Select("Table = " + name.EscapeSql() + " AND Create = 1");
                List<string> columns = new List<string>();
                foreach (DataRow r in cols)
                    columns.Add(r["Column"].AsString());

                List<GridColumn> delColumns = new List<GridColumn>();
                foreach (GridColumn col in gv.Columns)
                {
                    if (!columns.Contains(col.FieldName))
                        delColumns.Add(col);
                }
                foreach (GridColumn col in delColumns)
                {
                    try
                    {
                        gv.Columns.Remove(col);
                        Designer.DestroyComponent(col);
                    }
                    catch { }
                }
                if (LanguageProvider != null)
                {
                    foreach (GridColumn col in gv.Columns)
                        LanguageProvider.GetSettings(col).LngString = col.FieldName;
                }
            }
            AddControl(gc);
        }
    }
}
